import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LocalCacheService } from './local-cache/local-cache.service';
import { MqttService } from './mqtt/mqtt.service';
import CMD from './cmd'
import { DeviceService } from './device/device.service';

const cluster = require('cluster')

function getWorkNo() {
  if(process.env.instance_var != undefined) { //pm2模式
     return Number(process.env[process.env.instance_var])
  }else {
    return cluster.isPrimary ? 0 : process.env.workNo
  }
}

async function bootstrap() {
    const app = await NestFactory.createApplicationContext(AppModule);
    const configService = app.get(ConfigService)
    const localCache = app.get(LocalCacheService)
    const deviceService = app.get(DeviceService)

    const deviceToServerTopic = configService.get('mqtt.topic.deviceToServer') + '/' //设备主动发送给服务器的
    const serverReplyDeviceTopic = configService.get('mqtt.topic.serverReplyDevice') + '/' //服务器回复设备的


    const deviceConnectQueue = configService.get('local.deviceConnectQueue') //设备上线，下线
    const devicePortQueue = configService.get('local.devicePortQueue') //设备端口
    const deivceUploadStatusQueue = configService.get('local.deivceUploadStatusQueue') //设备上报状态图
    const replyDeviceChargeStrategyQueue = configService.get('local.replyDeviceChargeStrategyQueue') //回复设备请求充电策略
    const realTimeInfoQueue = configService.get('local.realTimeInfoQueue')
    
    const mqtt = app.get(MqttService)
    await mqtt.connect()

    const workNo = getWorkNo()

    if(workNo == 0) {
      //这是设备->服务器，

      mqtt.message(async (topic, msg) => {
        console.log(topic)
        console.log(msg)
        const cmdType = msg.cmdType 
        let resData:any = { packType : 1, result : 1,  cmdType}
        const topics = topic.split('/')
        const deviceId = topics[1]
        const replyTopic = serverReplyDeviceTopic + deviceId

        try {

          let data:any = { deviceId }
          
          if(cmdType == CMD.CMD_LOGIN_NET || cmdType == CMD.CMD_LOGOUT_NET) { //设备注册,登出
            if(cmdType == CMD.CMD_LOGIN_NET) {
              resData.loginResult = 1
              data.status = 1
              localCache.store.lpush(devicePortQueue, JSON.stringify({deviceId, status : msg.outletStatus})) //把端口状态加入队列
            }else {
              data.status = 0
            }
            localCache.store.lpush(deviceConnectQueue, JSON.stringify(data))
            mqtt.publish(replyTopic, resData)
          }else if(cmdType == CMD.CMD_HEART_BEAT_PACK) { //心跳
            localCache.store.lpush(devicePortQueue, JSON.stringify({deviceId, status : msg.outletStatus})) //把端口状态加入队列
            mqtt.publish(replyTopic, resData)
          }else if(cmdType == CMD.CMD_OUTLET_STATUS) { //设备上报状态
            localCache.store.lpush(deivceUploadStatusQueue, JSON.stringify({deviceId, portNo : msg.outletNum, data : msg.keyType})) //状态加入队列
            mqtt.publish(replyTopic, resData)
          }else if(cmdType == CMD.CMD_DEV_CHK_SYS_RUN_PARA) { //设备主动请求充电策略
            localCache.store.lpush(replyDeviceChargeStrategyQueue, deviceId)
          }else if(cmdType == CMD.CMD_GET_TIME) { //DEV_REQ_TYPE_TIME,DEV_REQ_TYPE_DEV_SN,DEV_REQ_TYPE_AGENT_ID
            const reqType = msg.reqType
            if(reqType == 'DEV_REQ_TYPE_TIME') { //请求时间
              const date = new Date()
              const y = date.getFullYear()
              const m = String(date.getMonth() + 1).padStart(2, '0')
              const d = String(date.getDate()).padStart(2, '0')
              const h = String(date.getHours()).padStart(2, '0')
              const minu = String(date.getMinutes()).padStart(2, '0')
              const s = String(date.getSeconds()).padStart(2, '0')
              resData.DEV_REQ_TYPE_TIME = `${y}-${m}-${d},${h}:${minu}:${s}`
              mqtt.publish(replyTopic, resData)
            }else{
              deviceService.device(deviceId).then((device:any) => {
                if(!device) {
                  resData[reqType] = 0
                  mqtt.publish(replyTopic, resData)
                }else if(reqType == 'DEV_REQ_TYPE_DEV_SN') {
                  resData[reqType] = device.deviceId
                  mqtt.publish(replyTopic, resData)
                }else if(reqType == 'DEV_REQ_TYPE_AGENT_ID') {
                  resData[reqType] = device.merchantId
                  mqtt.publish(replyTopic, resData)
                } 
              })
              
            }
          }else if(cmdType == CMD.CMD_HEART_BEAT_PACK) { //充电曲线
            localCache.store.lpush(realTimeInfoQueue, JSON.stringify(msg))
          }

          
        } catch (error) {
          console.log(error)
          resData.result = 3
          mqtt.publish(serverReplyDeviceTopic + deviceId, resData)
        }
      })

      await mqtt.subscribe(deviceToServerTopic + '+', 2)

      if(cluster.isPrimary) {
        for(let i = 1; i <= 2; i ++) {
          cluster.fork({workNo : i})
        }
      }
    }
}
bootstrap();
